package com.develop.mybluetooth.fragment

import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.text.isDigitsOnly
import androidx.recyclerview.widget.LinearLayoutManager
import com.develop.bluetoothlib.MyBluetooth
import com.develop.bluetoothlib.exception.BluetoothException
import com.develop.bluetoothlib.inter.SendCallBack
import com.develop.mybluetooth.bean.BMessage
import com.develop.mybluetooth.utils.Tools
import com.develop.mybluetooth.adapter.MessageAdapter
import com.develop.mybluetooth.databinding.FragmentBleConsoleBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import t
import java.math.BigInteger
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale


class BLEConsoleFragment : Fragment() {


    private var myBluetooth: MyBluetooth? = null

    private val TAG = "SPPFragment"

    private var bleBinding : FragmentBleConsoleBinding?= null
    private var adapter : MessageAdapter?= null
    private var linearLayoutManager : LinearLayoutManager ?= null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        myBluetooth = MyBluetooth.getInstance()
        receiverListener()
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        bleBinding = FragmentBleConsoleBinding.inflate(layoutInflater)
        return bleBinding?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        linearLayoutManager = LinearLayoutManager(context)
        bleBinding?.rvSppMessages?.layoutManager = linearLayoutManager
        adapter =  MessageAdapter()
        bleBinding?.rvSppMessages?.adapter = adapter
        bleBinding?.tvSend?.setOnClickListener {
            Log.i(TAG, "点击发送")
            val content = bleBinding?.etInput?.text.toString().trim()
//            sendMsg(content)
        }

        bleBinding?.acbRxHex?.setOnCheckedChangeListener { compoundButton, b ->

        }
        bleBinding?.acbTimer?.setOnCheckedChangeListener { compoundButton, b ->
            if(!b){
                stopCoroutineTask()
            }
        }

        bleBinding?.tvClear?.setOnClickListener {
            rxCount = 0
            txCount = 0
            bleBinding?.tvRxCount?.text = "0"
            bleBinding?.tvTxCount?.text = "0"
            adapter?.itemCount?.let { it1 -> adapter?.removeAtRange(0..it1) }
        }
    }


    private fun timeFormat(timestamp : Long) : String{
        val sdf = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }

    private fun receiverListener(){
        MyBluetooth.getInstance().setReceiver { dataInputStream, result -> //设备发过来的数据将在这里出现
            Log.e(
                TAG,
                "收到蓝牙设备返回数据->" + Tools.bytesToHexString(result)
            )
            if(bleBinding?.acbTxHex?.isChecked == true){
                addMessage("接收数据 $result",false)
            }else{
                addMessage("接收数据 ${Tools.bytesToHexString(result)}",false)
            }
        }
    }

    private fun sendMsg(content : String){
        //调用发送器发送命令
        if(myBluetooth?.isConnected == false){
            addMessage("设备未连接",true)
            return
        }
        if(content.isEmpty()){
            return
        }

        val demoCommand = if(bleBinding?.acbRxHex?.isChecked == true){
            if(isHexadecimal(content)){
                val bigInt = BigInteger(content, 16)
                bigInt.toByteArray()
            } else {
                byteArrayOf()
                return
            }

        }else{
            //判断是否是纯数字
            if(content.isDigitsOnly()){
                content.toByteArray()
            }else{
                byteArrayOf()
                return
            }
        }


        if(bleBinding?.acbTimer?.isChecked == true){
            startCoroutineTask(demoCommand)
        }else{
            sendCommand(demoCommand)
        }
    }

    private fun sendCommand(demoCommand : ByteArray){
        myBluetooth?.send(demoCommand, object : SendCallBack {
            override fun onSending(command: ByteArray) {
                Log.i(TAG, "命令发送中...")
                addMessage(Tools.bytesToHexString(command),true)
            }

            override fun onSendFailure(bleException: BluetoothException) {
                Log.e(TAG, "发送命令失败->" + bleException.message)
                addMessage("发送失败",true)
            }
        })
    }

    // 启动协程
    private var job: Job? = null
    private fun startCoroutineTask(demoCommand : ByteArray) {
        val delayTime = bleBinding?.aetTimer?.text.toString()
        val delayLong = delayTime.toLong()
        if(delayLong > 0){
            job = CoroutineScope(Dispatchers.Default).launch {
                while (isActive) { // 循环执行
                    sendCommand(demoCommand)
                    delay(delayTime.toLong())
                }
            }
        }else{
            requireContext().t("请输入大于0的时间")
        }

    }

    private fun stopCoroutineTask() {
        job?.cancel()
    }



    private fun isHexadecimal(input: String): Boolean {
        val pattern = "^[0-9A-Fa-f]+\$"
        return input.matches(pattern.toRegex())
    }

    private var rxCount = 0
    private var txCount = 0
    fun addMessage(msg : String, isSent : Boolean){
        if(isSent){
            txCount ++
        }else{
            rxCount ++
        }

        bleBinding?.tvRxCount?.text = rxCount.toString()
        bleBinding?.tvTxCount?.text = txCount.toString()

        adapter?.addMessage(
            BMessage(
                msg,
                timeFormat(System.currentTimeMillis()),
                isSent
            )
        )
        val lastVisibleItemPosition = linearLayoutManager?.findLastCompletelyVisibleItemPosition()
        if (lastVisibleItemPosition == adapter?.itemCount!! - 2) {
            bleBinding?.rvSppMessages?.scrollToPosition(adapter?.itemCount!! - 1)
        }
    }

}